package com.chaosj.skill.zipkin.annotations

import brave.Span
import com.google.common.base.Splitter
import com.google.common.base.Strings
import ognl.Ognl
import ognl.OgnlContext
import ognl.OgnlException

import java.lang.reflect.Method

/**
 * @Description:
 * @author: caoyangjie
 * @date: 2019年12月2019/12/6日 09:13
 * @Copyright: © 赢时胜
 */
class DefaultOgnlSpanParser implements ISpanParser{

    public static final int needArgLength = 3
    public static final String SERVICE_MAP = "serviceMap"
    public static final String SPLITTER_TARGET = "#"
    public static final String SEPARATOR_POINT = "."

    @Override
    String parserAnnotate(NewSpan yssSpan, Object[] args) {
        if( !Strings.isNullOrEmpty(yssSpan.annotate()) ){
            return yssSpan.annotate()
        }
        if( Strings.isNullOrEmpty(yssSpan.annotateExpression()) ){
            return ((Method)args[1]).getName()
        }
        String value = getObjectByExpression(args,yssSpan.annotateExpression()).toString()
        List<String> names = Splitter.on(SEPARATOR_POINT).splitToList(value)
        names.get(names.size()-1)
    }

    @Override
    String parserName(NewSpan yssSpan, Object[] args) {
        if( !Strings.isNullOrEmpty(yssSpan.name()) ){
            return yssSpan.name()
        }
        String value = getObjectByExpression(args,yssSpan.nameExpression()).toString()
        List<String> names = Splitter.on(SEPARATOR_POINT).splitToList(value)
        names.get(names.size()-1)
    }

    @Override
    void parserTag(NewSpan yssSpan, Object[] args, Span span) {
        try {
            for( String expression : yssSpan.tagExpression() ){
                Object value = getObjectByExpression(args, expression)
                if( value!=null ){
                    span.tag(expression.replace(SPLITTER_TARGET,""),value.toString())
                }
            }
        } catch (Exception e) {
        }
    }

    @Override
    boolean filter(NewSpan yssSpan, Object[] args) {
        true
    }

    private Object getObjectByExpression(Object[] args, String serviceMapServiceInfoClassName) {
        OgnlContext context = new OgnlContext()
        context.put(SERVICE_MAP,args[2])
        Object value = null
        try {
            value = Ognl.getValue(Ognl.parseExpression(serviceMapServiceInfoClassName), context, context.getRoot())
        } catch (OgnlException e) {
        }
        if( value==null ){
            return ""
        }
        return value
    }
}
